package com.boost.socialNetwork.server;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;


import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;


import com.boost.socialNetwork.client.UserService;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class UserServiceImpl extends RemoteServiceServlet implements
		UserService {

	public String authenticate(String userName, String password)
			throws IllegalArgumentException {
		EntityManager em = EMF.get().createEntityManager();
		double cur=System.currentTimeMillis();
		Query query = em.createQuery("select u from User u where userName = :username");
		query.setParameter("username", userName);
		@SuppressWarnings("unchecked")
		List<User> usrs = query.getResultList();
		System.out.println("Authenticate time: " + (System.currentTimeMillis()-cur));
		if (usrs == null || usrs.size() == 0) {
			em.close();
			return "user not found";
		}
		
		User user = usrs.get(0);
		if (!(user.getPassword().equals(password))) {
			em.close();
			return "wrong password";
		}
		putUserInSession(KeyFactory.keyToString(user.getId()));
		em.close();
		return "200 OK";
	}
	
	public void putUserInSession(String key) {
		HttpServletRequest httpServletRequest = getThreadLocalRequest();
		HttpSession session = httpServletRequest.getSession();
		session.setAttribute("userKey", key);
	}
	
	public String putCurrentPage(String page) {
		HttpServletRequest httpServletRequest = getThreadLocalRequest();
		HttpSession session = httpServletRequest.getSession();
		session.setAttribute("currentPage", page);
		return page;
	}
	
	public String getCurrentPage() {
		HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
		HttpSession session = httpServletRequest.getSession();
		System.out.println("gab el page " + (String) session.getAttribute("currentPage"));
		return (String) session.getAttribute("currentPage");
	}

	public String getConnected() {
		HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
		HttpSession session = httpServletRequest.getSession();
		return (String) session.getAttribute("userKey");
	}
	
	public List<String> retrieveIdeas(String id)
			throws IllegalArgumentException {
		double cur=System.currentTimeMillis();
		EntityManager em = EMF.get().createEntityManager();
		Key key = KeyFactory.stringToKey(id);
		/*pm.getFetchPlan().setGroup(FetchGroup.ALL);
		Query query = pm.newQuery(User.class);
		query.setFilter("id == :key");
		@SuppressWarnings("unchecked")
		List<User> usrs = (List<User>) query.execute(key);
		if(usrs == null || usrs.size() == 0) return null;*/
		User user = em.find(User.class, key);
		List<Idea> ideas = user.getIdeas();
		List<String> output = new ArrayList<String>();
		if(ideas.iterator().hasNext()){
			for(Idea i: ideas){
				output.add(KeyFactory.keyToString(i.getId())  + "," + i.getAuthor().getUserName() + "," + i.getDate().toString().substring(0, 10) + "," + i.getTitle() + "," + i.getContent());
			}
		}
		System.out.println("My Ideas time: " + (System.currentTimeMillis()-cur));
		em.close();
		return output;
	}


	public String register(String userName, String password, String firstName,
			String lastName, String country, String email) throws IllegalArgumentException {
		double cur=System.currentTimeMillis();
		EntityManager em = EMF.get().createEntityManager();
		Query query = em.createQuery("select u from User u where userName = :username");
		query.setParameter("username", userName);
		@SuppressWarnings("unchecked")
		List<User> usrs = (List<User>) query.getResultList();
		if(!(usrs == null || usrs.size() == 0)) return "Already exisits";
		
		try{
			User user = new User();
			user.setUserName(userName);
			user.setFirstName(firstName);
			user.setLastName(lastName);
			user.setCountry(country);
			user.setPassword(password);
			user.setEmail(email);
			user.setIdeas(new ArrayList<Idea>());
			em.persist(user);
			em.close();
		} catch(Exception e) {
			return "Cannot access the database";
		}
		
		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);
		try {
		Message msg = new MimeMessage(session);
		msg.setFrom(new InternetAddress(
		"hamada@inasbook.appspotmail.com",
		"boostSocialNetwork Admin"));
		msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
		email, "Mr. "+ "Hamada"));
		msg.setSubject("Your boostScoialNetwork.com account has been activated");
		msg.setText("Ahlan beek m3ana");
		Transport.send(msg);

		} catch (Exception e) {
		return "NO";
		}
		System.out.println("Register time: " + (System.currentTimeMillis()-cur));
		return "OK";
	}
	
	@Override
	 public String logout() {
		HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
		HttpSession session = httpServletRequest.getSession();
		session.removeAttribute("userKey");
		return "OK"; 
	 }	 	


	@Override
	public String createIdea(String userKey, String title, String content)
			throws IllegalArgumentException {
		double cur=System.currentTimeMillis();
		EntityManager em = EMF.get().createEntityManager();
		
		Key key = KeyFactory.stringToKey(userKey);
		try{
			User user = em.find(User.class, key);
			Idea idea = new Idea();
			idea.setTitle(title);
			idea.setContent(content);
			idea.setAuthor(user);
			idea.setDate(new Date());
			idea.setToBeNtoified(new ArrayList<String>());
			idea.setComments(new ArrayList<Comment>());
			idea.getToBeNtoified().add(user.getEmail());
			user.addIdea(idea);
			em.persist(idea);
		} catch (Exception e) {
			return "Datastore error!";
		}
		System.out.println("Create idea time : " + (System.currentTimeMillis()-cur));
		return "OK";
	}


	@Override
	public String deleteIdea(String ideaKey) throws IllegalArgumentException {
		try {
			EntityManager em = EMF.get().createEntityManager();
			Idea idea = em.find(Idea.class, KeyFactory.stringToKey(ideaKey));
			em.remove(idea);
			em.close();
			return "deleted";
		} catch (Exception e) {
			return "failed";
		}
	}


	@Override
	public String commentOnIdea(String ideaKey, String userKey, String content)
			throws IllegalArgumentException {
		EntityManager em = EMF.get().createEntityManager();
		User user = em.find(User.class,
				KeyFactory.stringToKey(userKey));
		String ideaName = "";
		Idea idea;
		try {
			Comment comment = new Comment();
			comment.setContent(content);
			comment.setDate(new Date());
			idea = em.find(Idea.class, KeyFactory.stringToKey(ideaKey));
			ideaName = idea.getTitle();
			comment.setIdea(idea);
			comment.setAuthor(user.getUserName());
			idea.getComments().add(comment);
			if(!idea.getToBeNtoified().contains(user.getEmail()))
			idea.getToBeNtoified().add(user.getEmail());
			em.persist(comment);
			em.close();
		} catch (Exception e) {
			e.printStackTrace();
			em.close();
			return "NO";
		}
		Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        String msgBody = "User " + user.getUserName() + "has commented on idea " + ideaName;

		try {
		Message msg = new MimeMessage(session);
		msg.setFrom(new InternetAddress(
		"sekkina@inasbook.appspotmail.com",
		"Admin Sekkina"));
		List<String> emails = idea.getToBeNtoified();
		if(emails.iterator().hasNext()){
			for(String email: emails){
				if(!email.equals(user.getEmail())){
					msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
							email , "Dear User"));
							msg.setSubject("Comment on idea");
							msg.setText(msgBody);
				}
			}
			Transport.send(msg);
		}

		} catch (Exception e) {
		return "NO";
		}
	
		return "OK";
	}


	@Override
	public List<String> retrieveOtherIdeas(String userKey)
			throws IllegalArgumentException {
		double cur=System.currentTimeMillis();
		EntityManager em = EMF.get().createEntityManager();
        User user = em.find(User.class, KeyFactory.stringToKey(userKey));
        List<Idea> userIdeas = user.getIdeas();
        @SuppressWarnings("unchecked")
        List<Idea> ideas = (List<Idea>) em.createQuery("Select i from Idea i").getResultList();
        //ideas.removeAll(userIdeas);
		System.out.println("Retrieve other ideas time: " + (System.currentTimeMillis()-cur));
        ArrayList<String> output = new ArrayList<String>();
        if(ideas.iterator().hasNext()){
                for(Idea i: ideas){
                        if(userIdeas.contains(i)) continue;
                        output.add(KeyFactory.keyToString(i.getId()) + "," + i.getAuthor().getUserName() + "," + i.getDate().toString().substring(0, 10) + "," + i.getTitle() + "," + i.getContent());
                }
        }
        return output;
	  }
	
	    public List<String> retrieveComments(String ideaKey) throws IllegalArgumentException {	
		EntityManager em = EMF.get().createEntityManager();
        Idea idea = em.find(Idea.class, KeyFactory.stringToKey(ideaKey));
        List<Comment> comments = idea.getComments();
        ArrayList<String> output = new ArrayList<String>();
        if(comments.iterator().hasNext()){
                for(Comment c: comments){
                        System.out.println(c.getId());
                        System.out.println("Key: " + c.getId() +  " Author: " + c.getAuthor() + " date: " + c.getDate() + " content: "+ c.getContent());
                        output.add(KeyFactory.keyToString(c.getId()) + "," + c.getAuthor()+ "," + c.getDate().toString().substring(0, 10) + "," +  c.getContent());
                }
        }
        return output;
	}

		@Override
		public String getUserName() {
			EntityManager em = EMF.get().createEntityManager();
			String key = getConnected();
			Key userKey = KeyFactory.stringToKey(key);
			try{
				User user = em.find(User.class, userKey);
				return user.getUserName();
			} catch(Exception e){
				return "";
			}
		}
	
	
}
